package faceattendsystem.servlet;

import java.awt.Image;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import faceattendsystem.entity.Employee;
import faceattendsystem.entity.Mechanism;
import faceattendsystem.service.IEmployeeService;
import faceattendsystem.serviceImpl.EmployeeServiceImpl;
import net.sf.json.JSONObject;

public class AddEmployeeServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		IEmployeeService employeeService = new EmployeeServiceImpl();
		Map<String, String> errors = new HashMap<String, String>();

		String type = req.getParameter("type");
		String mechid = null, empid = null, name = null, password = null, idnumber = null, picmd5 = null, power = null,
				state = null;

		// 得到上传文件的保存目录，将上传的文件存放于WEB-INF目录下，不允许外界直接访问，保证上传文件的安全
		String savePath = "C:\\Image\\Base";
		String tempPath = "C:\\Image\\temp";// 上传时生成的临时文件保存目录
		File tmpFile = new File(tempPath);
		if (!tmpFile.exists()) {
			// 创建临时目录
			tmpFile.mkdir();
		}

		String tempSavePath = this.getServletContext().getRealPath("/upload");
		File file = new File(tempSavePath);
		// 判断上传文件的保存目录是否存在
		if (!file.exists() && !file.isDirectory()) {
			//System.out.println(tempSavePath + "目录不存在，需要创建");
			// 创建目录
			file.mkdir();
		}
		
		// 消息提示
		String message = "";
		// 使用Apache文件上传组件处理文件上传步骤：
		// 1、创建一个DiskFileItemFactory工厂
		DiskFileItemFactory factory = new DiskFileItemFactory();
		// 设置工厂的缓冲区的大小，当上传的文件大小超过缓冲区的大小时，就会生成一个临时文件存放到指定的临时目录当中。
		factory.setSizeThreshold(1024 * 100);// 设置缓冲区的大小为100KB，如果不指定，那么缓冲区的大小默认是10KB
		// 设置上传时生成的临时文件的保存目录
		factory.setRepository(tmpFile);
		// 2、创建一个文件上传解析器
		ServletFileUpload upload = new ServletFileUpload(factory);
		// 监听文件上传进度
		// upload.setProgressListener(new ProgressListener() {
		// public void update(long pBytesRead, long pContentLength, int arg2) {
		// System.out.println("文件大小为：" + pContentLength + ",当前已处理：" +
		// pBytesRead);
		// }
		// });
		// 解决上传文件名的中文乱码
		upload.setHeaderEncoding("UTF-8");
		// 3、判断提交上来的数据是否是上传表单的数据
		if (!ServletFileUpload.isMultipartContent(req)) {
			// 按照传统方式获取数据
			return;
		}
		// System.out.println("非传统");
		// 设置上传单个文件的大小的最大值，目前是设置为1024*1024字节，也就是1MB
		//upload.setFileSizeMax(1024 * 1024);
		// 4、使用ServletFileUpload解析器解析上传数据，解析结果返回的是一个List<FileItem>集合，每一个FileItem对应一个Form表单的输入项
		try {
			List<FileItem> list = upload.parseRequest(req);
			for (FileItem item : list) {
				// 如果fileitem中封装的是普通输入项的数据
				if (item.isFormField()) {
					String tname = item.getFieldName();
					// 解决普通输入项的数据的中文乱码问题
					String value = item.getString("UTF-8");
				//	System.out.println(tname + " " + value);
					if (tname.equals("mechid")) {
						mechid = value;
					}
					if (tname.equals("empid")) {
						empid = value;
						if (type.equals("add")) {
							boolean repeat = employeeService.isRepeatEmpid(empid);
							if (!empid.matches("\\d+")) {
								errors.put("empid", "工号须是数字!");
							} else if (empid.length() > 8) {
								errors.put("empid", "工号长度不能超过8位!");
							} else if (repeat) {
								errors.put("empid", "工号已存在!");
							}
						}
					}
					if (tname.equals("name")) {
						name = value;
						if (name.length() > 20||name.length() < 1) {
							errors.put("name", "姓名长度须在1~20位之间!");
						}
					}
					if (tname.equals("password")) {
						password = value;
						if (type.equals("add")) {
							if (password.length() < 6 || password.length() > 15) {
								errors.put("password", "密码长度须在6~15之间!");
							} else {
								try {
									password = EncoderByMd5(password);
								} catch (NoSuchAlgorithmException e) {
									//System.out.println("密码加密出错!");
								}
							}
						}
					}
					if (tname.equals("idnumber")) {
						idnumber = value;
						Employee employee = employeeService.isRepeatIdnumber(idnumber);
						if(idnumber.length()!=18){
							errors.put("idnumber", "身份证号长度须是18位!");
						}else if (!idnumber.matches("^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$")) {
							errors.put("idnumber", "身份证号格式输写错误!");
						} else if(employee!=null&&!employee.getEmpid().equals(empid)){
							errors.put("idnumber", "身份证号已存在!");
						}
					}
					if (tname.equals("power")) {
						power = value;
					}
					if (tname.equals("state")) {
						state = value;
					}

				} else {// 如果fileitem中封装的是上传文件
						// 得到上传的文件名称，

					String filename = item.getName();
					//System.out.println("filename="+filename);
					
					if (type.equals("update")) {//若修改没有更改图片
						if(filename == null || filename.trim().equals("")){
							Employee employee = employeeService.queryByEmpid(empid);
							picmd5 = employee.getPicmd5();
						}
					}
					
					if (filename == null || filename.trim().equals("")) {
						continue;
					}
					// 注意：不同的浏览器提交的文件名是不一样的，有些浏览器提交上来的文件名是带有路径的，如：
					// c:\a\b\1.txt，而有些只是单纯的文件名，如：1.txt
					// 处理获取到的上传文件的文件名的路径部分，只保留文件名部分
					filename = filename.substring(filename.lastIndexOf("\\") + 1);
					// 得到上传文件的扩展名
					String fileExtName = filename.substring(filename.lastIndexOf(".") + 1);
					if (!fileExtName.equals("bmp")) {
						errors.put("picmd5", "头像图片须是bmp格式!");
					}
					// 如果需要限制上传的文件类型，那么可以通过文件的扩展名来判断上传的文件类型是否合法
					// System.out.println("上传的文件的扩展名是：" + fileExtName);

					if (errors.size() == 0) {// 如果没有错误
						// 获取item中的上传文件的输入流
						InputStream in = item.getInputStream();
						// 得到文件保存的名称
						String saveFilename = empid + "." + fileExtName;
						// 得到文件的保存目录
						String realSavePath = makePath(mechid, savePath);
						// 创建一个文件输出流
						FileOutputStream out1 = new FileOutputStream(realSavePath + "\\" + saveFilename);
						FileOutputStream out2 = new FileOutputStream(tempSavePath + "\\" + saveFilename);
						// 创建一个缓冲区
						byte buffer[] = new byte[1024];
						int len = 0;
						while ((len = in.read(buffer)) > 0) {
							out1.write(buffer, 0, len);
							out2.write(buffer, 0, len);
						}
						// 关闭输入流,关闭输出流
						in.close();
						out1.close();
						out2.close();
						
						// 删除处理文件上传时生成的临时文件
						item.delete();
						message = "文件上传成功！";

						Image image = ImageIO.read(new File(realSavePath + "\\" + saveFilename));
						try {
							picmd5 = EncoderByMd5(image.toString());
						} catch (NoSuchAlgorithmException e) {
							errors.put("picmd5", "请换一张头像图片!");
						}
					}
				}
			}
		}catch (FileUploadException e) {
			errors.put("picmd5", "头像图片上传失败!");
		}

		if (errors.size() != 0) {
			errors.put("flag", "1");
		} else {
			errors.put("flag", "0");
			Employee employee = new Employee();
			Mechanism mechanism = new Mechanism();
			mechanism.setMechid(mechid);
			employee.setMechanism(mechanism);
			employee.setEmpid(empid);
			employee.setName(name);
			employee.setIdnumber(idnumber);
			employee.setPicmd5(picmd5);
			employee.setPower(power);
			employee.setState(state);
			employee.setPassword(password);
		//	System.out.println(employee);

			if (type.equals("add")) {
				employeeService.add(employee);
			} else if (type.equals("update")) {
				employeeService.update(employee);
			}
		}

		//System.out.println("flag=" + errors.get("flag"));
		JSONObject json = JSONObject.fromObject(errors);// 使用JSONobject将map对象转换成json对象
		PrintWriter out = resp.getWriter();
		out.print(json);
	}

	/**
	 * 更改文件路径
	 * 
	 * @param mechid
	 * @param savePath
	 * @return
	 */
	private String makePath(String mechid, String savePath) {
		String dir = savePath; // 机构号
		File file = new File(dir);// File既可以代表文件也可以代表目录
		if (!file.exists()) {
			file.mkdirs();
		}
		return dir;
	}

	/**
	 * md5加密
	 * 
	 * @param str
	 * @return
	 * @throws NoSuchAlgorithmException
	 */
	private String EncoderByMd5(String str) throws NoSuchAlgorithmException {
		MessageDigest md = MessageDigest.getInstance("MD5");
		md.update(str.getBytes());
		byte b[] = md.digest();
		StringBuffer buf = new StringBuffer("");
		for (int offset = 0; offset < b.length; offset++) {
			int i = b[offset];
			if (i < 0)
				i += 256;
			if (i < 16)
				buf.append("0");
			buf.append(Integer.toHexString(i));
		}
		return buf.toString();
	}
}